// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-02-08

package shop

import (
	"context"
	"gitee.com/go-libs/db-xorm/db"
	"gitee.com/go-libs/log"
	"integration/app/errs"
	"integration/app/lib/conf"
	"integration/app/lib/nod"
	"integration/app/lib/nod/api"
	"integration/app/lib/nod/customer"
	"integration/app/models"
	"integration/app/requests/shop/order"
	"integration/app/services"
)

// OrderLogic
// 订单逻辑.
type OrderLogic struct{}

// GetCrmebOrder
// 读取订单数据.
func (o *OrderLogic) GetCrmebOrder(ctx context.Context, sess *db.Session, id int) (model *models.Order, err error) {
	if model, err = services.NewOrderService(sess).GetById(ctx, id); err != nil {
		err = errs.ErrDatabaseQueryFailed
		return
	}
	if model == nil {
		err = errs.ErrOrderNotFound
	}
	return
}

// GetCrmebOrderCart
// 读取订单商品数据.
//
// 商城(CRMEB)订单中, 商品数据以快照(JSON)格式保存在 eb_store_order_cart_info 表的
// cart_info 字段中.
func (o *OrderLogic) GetCrmebOrderCart(ctx context.Context, sess *db.Session, id int) (list []*models.OrderCartInfo, err error) {
	if list, err = services.NewOrderCartInfoService(sess).ListByOrderId(ctx, id); err != nil {
		err = errs.ErrDatabaseQueryFailed
	}
	return
}

// GetCrmebOrderStatus
// 读取订单状态数据.
//
// 商城(CRMEB)订单发生状态变更时, 会向 eb_store_order_status 表添加一条数据, 该方法读
// 取其原始数据.
func (o *OrderLogic) GetCrmebOrderStatus(ctx context.Context, sess *db.Session, req *order.StatusRequest) (status *models.OrderStatus, err error) {
	if status, err = services.NewOrderStatusService(sess).GetByStatusRequest(ctx, req); err != nil {
		err = errs.ErrDatabaseQueryFailed
		return
	}
	if status == nil {
		err = errs.ErrOrderStatusNotFound
	}
	return
}

// InitErpCustomer
// 初始化ERP客户.
//
// 检查本地客户是否已创建, 若未创建或客户信息与订单信息不致则重新上报.
func (o *OrderLogic) InitErpCustomer(cts context.Context, agent *conf.ErpAgent, order *models.Order) (bean *models.ErpCustomer, err error) {
	var (
		ctx     = log.NewContextForChildInfo(cts, `init erp customer`)
		entity  *customer.Entity
		number  = agent.GenerateCustomerNo(order.Uid)
		res     *api.PostCustomerResponse
		service = services.NewErpCustomerService()
	)

	// 1. 生成入参.
	if entity, err = nod.Builder.Customer(ctx, agent, order); err != nil {
		return
	}

	// 2. 读取客户.
	if bean, err = service.GetByErpNumber(ctx, number); err != nil {
		err = errs.ErrDatabaseQueryFailed
		return
	}

	// 3. 客户存在.
	if bean != nil {
		// 从未修改.
		if entity.NotChanged(bean) {
			log.Infofc(ctx, `customer found: erp_id="%d", erp_number="%s", erp_name="%s"`, bean.ErpId, bean.ErpNumber, bean.ErpName)
			return
		}

		// 数据变更.
		entity.Id = bean.ErpId
	}

	// 4. 上报客户.
	if res, err = nod.Api.PostCustomer(ctx, agent, entity); err != nil {
		return
	}

	// 5. 创建本地.
	if bean != nil {
		bean.ErpId = res.CustomerId
		bean.ErpFrame = entity.Frame
		bean.ErpNumber = entity.Number
		bean.ErpName = entity.Name
		bean.ErpContactName = entity.Contact[0].Name
		bean.ErpContactPhone = entity.Contact[0].Phone
		bean.ErpContactAddress = entity.Contact[0].Address
		_, err = service.Edit(ctx, bean)
	} else {
		bean, err = service.Add(ctx, &models.ErpCustomer{
			ErpId:             res.CustomerId,
			ErpFrame:          entity.Frame,
			ErpNumber:         entity.Number,
			ErpName:           entity.Name,
			ErpContactName:    entity.Contact[0].Name,
			ErpContactPhone:   entity.Contact[0].Phone,
			ErpContactAddress: entity.Contact[0].Address,
		})
	}
	if err == nil {
		log.Infofc(ctx, `customer update: erp_id="%d", erp_number="%s", erp_name="%s"`, bean.ErpId, bean.ErpNumber, bean.ErpName)
	}
	return
}

// LoadCrmebOrder
// 初始化CRMEB订单数据.
func (o *OrderLogic) LoadCrmebOrder(ctx context.Context, agent *conf.ErpAgent, req *order.StatusRequest) (order *models.Order, orderStatus *models.OrderStatus, orderCarts []*models.OrderCartInfo, err error) {
	var sess *db.Session
	if sess, err = db.Config.GetSlave(ctx, agent.ConnectionKey); err != nil {
		err = errs.ErrDatabaseConnectFailed
		return
	}
	if orderStatus, err = o.GetCrmebOrderStatus(ctx, sess, req); err == nil {
		if order, err = o.GetCrmebOrder(ctx, sess, orderStatus.Oid); err == nil {
			if order.Pid.Split() {
				err = errs.ErrOrderSplit
			} else {
				orderCarts, err = o.GetCrmebOrderCart(ctx, sess, orderStatus.Oid)
			}
		}
	}
	return
}
